package com.aspirecn.core.datacache;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.validator.routines.UrlValidator;
import org.apache.log4j.Logger;

import com.aspirecn.core.commons.Configuration;
import com.aspirecn.core.commons.ObjectUtils;
import com.aspirecn.core.commons.SecurityUtils;
import com.aspirecn.core.object.XSSExclude;
import com.aspirecn.core.object.XSSJumper;
import com.aspirecn.core.object.XSSProject;

/**
 * XSS校验内容缓存
 * 
 * @author wangxinning
 * 
 */
public class XssCache extends BaseLocalCache {

	private final static Logger logger = Logger.getLogger(XssCache.class);

	private static XssCache instance = new XssCache();

	private Map<String, XSSProject> xssProjectMap = new HashMap<String, XSSProject>();

	private XssCache() {
		this.dataFile = new File(Configuration.getInstance()
				.getDownloadFilePath() + File.separator + "aspirexss.xml");
		load();
	}

	public static XssCache getInstance() {
		return instance;
	}

	@Override
	public void load() {

		if (!loading.getAndSet(true)
				&& Configuration.getInstance().switchXSSCache() 
				&& this.dataFile.exists()) {

			// 数据少，直接清
			clear();

			try {
				XMLConfiguration config = new XMLConfiguration(this.dataFile);

				int maxno = config.getMaxIndex("project");
				
				for (int i = 0; i <= maxno; i++) {
					XSSProject defaultXSSProject = this.getXSSProject("default");
					if( defaultXSSProject == null )
					{
						defaultXSSProject = new XSSProject();
					}
					
					XSSProject xssProject = new XSSProject();

					xssProject.setHost(config.getString("project(" + i
							+ ").host"));
					xssProject.setErrorurl(config.getString("project(" + i
							+ ").errorurl",defaultXSSProject.getErrorurl()));
					xssProject.setStarttime(config.getString("project(" + i
							+ ").starttime",defaultXSSProject.getStarttime()));
					xssProject.setEndtime(config.getString("project(" + i
							+ ").endtime",defaultXSSProject.getEndtime()));
					xssProject.setParametername_filter(StringUtils
							.substringsBetween(
									config.getString("project(" + i
											+ ").parametername_filter"), "[",
									"]"));
					if( ArrayUtils.isEmpty(xssProject.getParametername_filter()) )
					{
						xssProject.setParametername_filter(defaultXSSProject.getParametername_filter());
					}
					xssProject.setParametervalue_filter(StringUtils
							.substringsBetween(
									config.getString("project(" + i
											+ ").parametervalue_filter"), "[",
									"]"));
					if( ArrayUtils.isEmpty(xssProject.getParametervalue_filter()) )
					{
						xssProject.setParametervalue_filter(defaultXSSProject.getParametervalue_filter());
					}

					int excludesmaxno = config.getMaxIndex("project(" + i
							+ ").excludes.exclude");
					
					List<XSSExclude> excludes = new ArrayList<XSSExclude>();
					for (int z = 0; z <= excludesmaxno; z++) {
						String[] keywords = StringUtils.substringsBetween(
								config.getString("project(" + i
										+ ").excludes.exclude(" + z
										+ ").keywords"), "[", "]");
						String[] nofilter_parametername = StringUtils
								.substringsBetween(
										config.getString("project(" + i
												+ ").excludes.exclude(" + z
												+ ").nofilter_parametername"),
										"[", "]");

						if (ArrayUtils.isNotEmpty(keywords)
								&& ArrayUtils
										.isNotEmpty(nofilter_parametername)) {
							XSSExclude xssExclude = new XSSExclude();
							xssExclude.setKeywords(keywords);
							xssExclude
									.setNofilter_parametername(nofilter_parametername);
							excludes.add(xssExclude);
						}
					}
					xssProject
							.setExcludes(ObjectUtils.isEmptyList(excludes) ? null : excludes);
					
					//2013-08-23新增，符合条件跳转逻辑
					int jumpersmaxno = config.getMaxIndex("project(" + i
							+ ").jumper.condition");					
					List<XSSJumper> jumpers = new ArrayList<XSSJumper>();
					for (int z = 0; z <= jumpersmaxno; z++) {
						String[] keywords = StringUtils.substringsBetween(
								config.getString("project(" + i
										+ ").jumper.condition(" + z
										+ ").keywords"), "[", "]");
						String jumpurl = config.getString("project(" + i
								+ ").jumper.condition(" + z
								+ ").jumpurl");
						
						if (ArrayUtils.isNotEmpty(keywords)
								&& StringUtils.isNotBlank(jumpurl)) {
							XSSJumper xssJumper = new XSSJumper();
							xssJumper.setKeywords(keywords);
							xssJumper.setJumpurl(jumpurl);
							jumpers.add(xssJumper);
						}						
					}
					xssProject
					.setJumpers( ObjectUtils.isEmptyList(jumpers) ? null : jumpers);
					
					xssProjectMap.put(xssProject.getHost(), xssProject);
				}
				
				updateFileDownloadTime();
				
				logger.info("xss校验信息加载完成");
				
			} catch (Exception e) {
				logger.error("加载xss安全校验信息出现异常", e);
			}

		} else {
			logger.info("配置关闭，xss校验信息未加载");
		}

		loading.set(false);
	}

	@Override
	public void clear() {

		xssProjectMap.clear();
	}

	@Override
	public void reload() {

		if (this.fileIsChange()) {
			this.clear();
			this.load();
		} else {
			logger.info("没变化，xss校验信息未加载");
		}
	}

	public XSSProject getXSSProject(String host) {
		XSSProject retXSSProject = this.xssProjectMap.get(host);		
		XSSProject defaultXSSProject = this.xssProjectMap.get("default");		
		if (retXSSProject == null) {
			retXSSProject = defaultXSSProject;
		}
		else
		{
			//过滤值不存在，用default补足
			if( ArrayUtils.isEmpty(retXSSProject.getParametername_filter()) )
			{
				retXSSProject.setParametername_filter(defaultXSSProject.getParametername_filter());
			}
			
			if( ArrayUtils.isEmpty(retXSSProject.getParametervalue_filter()) )
			{
				retXSSProject.setParametervalue_filter(defaultXSSProject.getParametervalue_filter());
			}
		}

		return retXSSProject;
	}

	// public List<String> getParameterNameList() {
	// if (this.isLoading()) {
	// return null;
	// }
	//
	// return this.parameterNameList;
	// }
	//
	// public List<String> getParameterValueList() {
	// if (this.isLoading()) {
	// return null;
	// }
	//
	// return this.parameterValueList;
	// }

	public static void main(String[] args) {
		XssCache xssCache = XssCache.getInstance();
		xssCache.load();

		List<XSSJumper> jumpers = xssCache.getXSSProject("a.10086.cn").getJumpers();
		
		//System.out.println(xssCache.getXSSProject("aaa"));
		System.out.println(jumpers);
		
		System.out.println( SecurityUtils.calJumper(jumpers, "http://a.10086.cn/aaa/ddd/fff/c=111&p=222") );
		
		String u = "http://a.10086.cn/aaa/ddd/fff/c=111&p=222";
		System.out.println(UrlValidator.getInstance().isValid("   "));
		
	}
}
